#include "messagedispatcher.h"
#include "misc/crudetimer.h"
#include <cassert>
#include "telegramtypes.h"


MessageDispatcher* MessageDispatcher::Instance()
{
	static MessageDispatcher instance;

	return &instance;
}

/*-------------------------------------------------------------------------------------------------------------*/
void MessageDispatcher::DispatchMessage(double	dTimeDelay,
										int		iSender,
										int		iReceiver,
										int		iMessage,
										void*	extraInfo)
{
	
	// Get a pointer to the receiver
	BaseGameEntity* pReceiver = EntityManager::Instance()->GetEntityByID(iReceiver);
	//BaseGameEntity* pSender   = EntityManager::Instance()->GetEntityByID(iSender);

	if (pReceiver == NULL)
	{
		return;
	}

	//create the telegram
	Telegram telegram(dTimeDelay, iSender, iReceiver, iMessage, extraInfo);

	// If there is no delay, send the message immediately
	if(dTimeDelay <= 0.0)
	{
		Discharge(pReceiver, telegram);
	}

	// Else calculate the time in which the message should be sent
	else
	{
		double dCurrentTime = Clock->GetCurrentTime();

		telegram.m_dTimeDelay = dCurrentTime + dTimeDelay;

		// Add it to the message queue
		PriorityQueue.insert(telegram);
	}
}
/*-------------------------------------------------------------------------------------------------------------*/
void MessageDispatcher::DispatchDelayedMessages()
{
	// Get current time
	double dCurrentTime = Clock->GetCurrentTime();

	// Now peek at the queue to see if any messages need dispatching.
	// remove all messages from the front of the queue that have gone
	// past their sell by date
	while(!PriorityQueue.empty() &&
		  (PriorityQueue.begin()->m_dTimeDelay < dCurrentTime) && 
		  (PriorityQueue.begin()->m_dTimeDelay > 0) )
	{
		// Read the message from the front of the queue
		const Telegram& message = *PriorityQueue.begin();

		//find the recipient
		BaseGameEntity* pReceiver = EntityManager::Instance()->GetEntityByID(message.m_iReceiver);

		cout << "\nQueued telegram ready for dispatch: Sent to " 
			<< GetEntityName(pReceiver->ID()) << ". Msg is " << message.m_iMessage;

		// Send the message to the recipient
		Discharge(pReceiver, message);

		//remove it from the queue
		PriorityQueue.erase(PriorityQueue.begin());
	}
}

/*-------------------------------------------------------------------------------------------------------------*/
void MessageDispatcher::Discharge(BaseGameEntity* pReceiver, const Telegram& telegram)
{
	if (!pReceiver->HandleMessage(telegram))
	{
		//telegram could not be handled
		cout << "Message not handled";
	}
}
